package cate.game.role.res.compose;

import cate.common.table.res.compose.ComposeItemRow;
import cate.common.util.TimeTool;
import cate.common.util.XT;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.res.compose.msg.ItemComposeResp;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@NoteClass(value = "物品合成")
public class ItemCompose extends RoleDependent {

    @NoteField(value = "当前可合成记录", detail = "<id,次数>")
    public Map<Integer, Integer> recordMap;


    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (recordMap == null) {
            recordMap = new HashMap<>();
        }
    }

    public ItemCompose() {
    }

    /**
     * 合成物品
     *
     * @param id
     * @param num
     * @return
     */
    public EcResult<Void> composeItems(int id, int num) {
        EcResult r = new EcResult();
        if (num == 0) {
            return r.fail("数量为0！");
        }
        ComposeItemRow row = role.getGame().table.compose.item.get(id);
        r = checkValid(id, num, row);
        if (!r.ok()) {
            return r.fail(r.message);
        }
        MixRes cost = new MixRes(row.costStr);
        cost.multiply(num);
        cost.consumeDirect(role);
        MixRes reward = new MixRes();
        for (int i = 0; i < num; i++) {
            if (XT.randomIndex(GDCompose.RATE_B) - row.rate > 0) {
                reward.addList(new MixRes(row.failStr));
                continue;
            }
            MixRes targetReward = new MixRes(row.targetStr);
            targetReward.items.forEach(item->role.getHistory().action.itemComposeTargetNum(item));
            reward.addList(targetReward);
        }
        reward.add(role);
        role.getGame().notice.dialogReward(role, reward);

        recordMap.putIfAbsent(id, 0);
        int time = recordMap.get(id) + num;
        time = Math.max(0, time);
        recordMap.put(id, time);
        noticeUpdate();
        return r.success();
    }

    public void noticeUpdate() {
        role.sendNow(new ItemComposeResp(this));
    }

    private EcResult<Void> checkValid(int id, int num, ComposeItemRow row) {
        EcResult r = new EcResult();
        if (row == null) {
            return r.fail("不存在当前合成方式");
        }
        //判断购买次数
        if (recordMap.containsKey(id) && recordMap.get(id) > row.limitTimes - num && row.limitTimes != GDCompose.NON_LIMIT) {
            return r.fail("次数不足");
        }
        //判断消耗
        MixRes cost = new MixRes(row.costStr);
        cost.multiply(num);
        EcResult<MixResItem> r_consume = cost.consumeCheck(role, null);
        if (!r_consume.ok()) {
            return r.fail("材料不足");
        }
        //时间
        if (row.endDay < role.getGame().getOpenDay()
                || row.startDay > role.getGame().getOpenDay()) {
            return r.fail("该时间段不能合成");
        }
        if ((!StringUtils.isEmpty(row.startTimeStr))
                && (TimeTool.parseTime(row.endTimeStr) < System.currentTimeMillis()
                || TimeTool.parseTime(row.startTimeStr) > System.currentTimeMillis())) {
            return r.fail("该时间段不能合成");
        }
        return r.success();
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        resetCheck(GDCompose.Cycle.DAY);
    }

    @Override
    public void onWeekSpan(boolean silence) {
        super.onWeekSpan(silence);
        resetCheck(GDCompose.Cycle.WEEK);
    }

    @Override
    public void onMonthSpan(boolean silence) {
        super.onMonthSpan(silence);
        resetCheck(GDCompose.Cycle.MONTH);
    }

    private void resetCheck(int cycleType) {
        List<Integer> resetList = new ArrayList<>();
        for (Integer id : recordMap.keySet()) {
            ComposeItemRow row = role.getGame().table.compose.item.get(id);
            if (row == null) {
                continue;
            }
            if (row.resetType == cycleType) {
                resetList.add(id);
            }
        }
        resetList.forEach(id -> recordMap.put(id, 0));
        noticeUpdate();
    }

    private int calDay(ComposeItemRow row) {
        if (!StringUtils.isEmpty(row.startTimeStr)) {
            return TimeTool.getDistanceDays(role.getGame().getOpenDay(), TimeTool.parseTime(row.startTimeStr));
        }
        if (row.startDay != 0) {
            return row.startDay;
        }
        return 1;
    }

    private void resetAdd(Integer id, int resetType, List<Integer> list, ComposeItemRow row) {
        int distanceDay;
        switch (resetType) {
            case GDCompose.Cycle.UN_CYCLE:
                break;
            case GDCompose.Cycle.DAY:
                list.add(id);
                break;
            case GDCompose.Cycle.WEEK:
                distanceDay = role.getGame().getOpenDay() - calDay(row);
                if (distanceDay != 0 && distanceDay % 7 == 0) {
                    list.add(id);
                }
                break;
            case GDCompose.Cycle.MONTH:
                distanceDay = role.getGame().getOpenDay() - calDay(row);
                if (distanceDay != 0 && distanceDay % 30 == 0) {
                    list.add(id);
                }
                break;
            default:
        }
    }
}
